package com.wyl.mybatis.intercept;

import cn.hutool.json.JSONArray;
import cn.hutool.json.JSONUtil;
import org.apache.ibatis.binding.MapperMethod;
import org.apache.ibatis.cache.CacheKey;
import org.apache.ibatis.executor.Executor;
import org.apache.ibatis.mapping.BoundSql;
import org.apache.ibatis.mapping.MappedStatement;
import org.apache.ibatis.plugin.*;
import org.apache.ibatis.session.ResultHandler;
import org.apache.ibatis.session.RowBounds;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.HashMap;
import java.util.Map;

/**
 * @Description 时间插件
 * @Author WuYiLong
 * @Date 2024/2/29 9:51
 */
@Intercepts({@Signature(
        type = Executor.class,
        method = "query",
        args = {
                MappedStatement.class,
                Object.class,
                RowBounds.class,
                ResultHandler.class
        }), @Signature(
        type = Executor.class,
        method = "query",
        args = {MappedStatement.class,
                Object.class,
                RowBounds.class,
                ResultHandler.class,
                CacheKey.class,
                BoundSql.class})})
public class TimeIntercept implements Interceptor {

    private final  static Logger log = LoggerFactory.getLogger(TimeIntercept.class);

    @Override
    public Object intercept(Invocation invocation) throws Throwable {
        Object[] args = invocation.getArgs();
        MappedStatement ms = (MappedStatement)args[0];
        MapperMethod.ParamMap pm = ( MapperMethod.ParamMap) args[1];
        Map<String, Object> paramsMap = new HashMap<>();
        if(pm != null) {
            pm.forEach((k,v)->{
                String key = String.valueOf(k);
                if(!key.contains("param")) {
                    paramsMap.put(String.valueOf(k),v);
                }
            });
        }

        BoundSql boundSql = ms.getBoundSql(ms.getParameterMap());
        // sql执行之前
        long startTime = System.currentTimeMillis();
        Object proceed = invocation.proceed();
        JSONArray jsonArray = JSONUtil.parseArray(proceed);
        long endTime = System.currentTimeMillis();
        log.info("----sql执行语句: {}",boundSql.getSql());
        log.info("----sql输入参数: {}", JSONUtil.toJsonStr(paramsMap));
        log.info("----sql输出结果数: {}", jsonArray.size());
        log.info("----sql执行花费时间: {}s", (endTime-startTime)/1000);
        // sql执行之后
        return proceed;
    }

    @Override
    public Object plugin(Object target) {
        if(target instanceof Executor) {
            return Plugin.wrap(target, this);
        }
        return target;
    }
}
